import json
import pyodbc
import logging
import time
import schedule
import os
import serial
print(serial.VERSION)

# 导入Modbus相关模块
from pymodbus.exceptions import ModbusException
from pymodbus.client import ModbusSerialClient

# 日志配置
log_dir = 'logs'
if not os.path.exists(log_dir):
    os.makedirs(log_dir)

# 创建logger
logger = logging.getLogger('data_forwarder')
logger.setLevel(logging.INFO)

# 设置日志格式
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# 初始化handler列表
handlers = []

# 加载配置以获取日志开关设置
config_path = 'config_server.json'
try:
    with open(config_path, 'r', encoding='utf-8') as f:
        config_preload = json.load(f)
        
    # 获取日志配置，默认开启所有日志
    log_config = config_preload.get('logging', {})
    console_enabled = log_config.get('console_enabled', True)
    file_enabled = log_config.get('file_enabled', True)
    
    # 创建控制台handler（只输出INFO级别及以上）
    if console_enabled:
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.INFO)
        console_handler.setFormatter(formatter)
        handlers.append(console_handler)
    
    # 创建按天命名的文件handler（记录DEBUG级别及以上）
    if file_enabled:
        # 使用TimedRotatingFileHandler并配置正确的参数
        from logging.handlers import TimedRotatingFileHandler
        
        # 基础日志文件名（不包含日期）
        base_log_file = os.path.join(log_dir, 'data_forwarder.log')
        
        file_handler = TimedRotatingFileHandler(
            base_log_file,
            when='midnight',  # 在午夜切换日志文件
            interval=1,  # 每天切换一次
            backupCount=30,  # 保留30天的日志文件
            encoding='utf-8',
            utc=False  # 使用本地时间
        )
        
        # 关键配置：设置文件名后缀为日期格式
        file_handler.suffix = "_%Y-%m-%d.log"
        
        # 确保日志文件按日期命名，而不是添加到原文件名后面
        # 例如：data_forwarder.log -> data_forwarder_2025-11-17.log
        import logging
        
        # 重写namer方法以确保正确的文件名格式
        def namer(name):
            # name参数格式: data_forwarder.log.2025-11-17
            # 我们需要将其转换为: data_forwarder_2025-11-17.log
            if name.endswith('.log'):
                # 当前正在使用的日志文件，不需要重命名
                return name
            # 分割文件名和日期部分
            base_name, date_part = name.rsplit('.', 1)
            # 移除基础名称中的.log后缀
            base_name = base_name.replace('.log', '')
            # 重新组合为正确的文件名格式
            return f"{base_name}_{date_part}.log"
        
        # 设置namer方法
        file_handler.namer = namer
        
        file_handler.setLevel(logging.INFO)
        file_handler.setFormatter(formatter)
        handlers.append(file_handler)
        
except Exception as e:
    # 如果加载配置失败，默认启用控制台和文件日志
    print(f"加载日志配置失败，使用默认配置: {str(e)}")
    
    # 创建控制台handler
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(formatter)
    handlers.append(console_handler)
    
    # 创建按天命名的文件handler
    from logging.handlers import TimedRotatingFileHandler
    
    # 基础日志文件名（不包含日期）
    base_log_file = os.path.join(log_dir, 'data_forwarder.log')
    
    file_handler = TimedRotatingFileHandler(
        base_log_file,
        when='midnight',  # 在午夜切换日志文件
        interval=1,  # 每天切换一次
        backupCount=30,  # 保留30天的日志文件
        encoding='utf-8',
        utc=False  # 使用本地时间
    )
    
    # 设置文件名后缀为日期格式
    file_handler.suffix = "_%Y-%m-%d.log"
    
    # 重写namer方法以确保正确的文件名格式
    def namer(name):
        # name参数格式: data_forwarder.log.2025-11-17
        # 我们需要将其转换为: data_forwarder_2025-11-17.log
        if name.endswith('.log'):
            # 当前正在使用的日志文件，不需要重命名
            return name
        # 分割文件名和日期部分
        base_name, date_part = name.rsplit('.', 1)
        # 移除基础名称中的.log后缀
        base_name = base_name.replace('.log', '')
        # 重新组合为正确的文件名格式
        return f"{base_name}_{date_part}.log"
    
    # 设置namer方法
    file_handler.namer = namer
    
    file_handler.setLevel(logging.INFO)
    file_handler.setFormatter(formatter)
    handlers.append(file_handler)

# 给logger添加所有handler
for handler in handlers:
    logger.addHandler(handler)

def load_config(config_path):
    """加载配置文件
    
    Args:
        config_path: 配置文件路径
    
    Returns:
        dict: 配置内容
    """
    try:
        with open(config_path, 'r', encoding='utf-8') as f:
            return json.load(f)
    except FileNotFoundError:
        logger.error(f"配置文件 {config_path} 不存在")
        raise
    except json.JSONDecodeError:
        logger.error(f"配置文件 {config_path} 格式错误")
        raise
    except Exception as e:
        logger.error(f"加载配置文件时发生错误: {str(e)}")
        raise

# 全局变量声明
config = None
previous_data = {}
# 存储数据源和参数组合的字典，用于快速查找
# 格式: data_source_param_map["dataSource_param"] = True
# 用于在get_latest_data中检查是否需要查询该组合
data_source_param_map = {}
# 持久化Modbus客户端
modbus_client = None

def validate_data_source_param(f_meter_code, f_meter_param_code):
    """验证F_MeterCode和F_MeterParamCode是否在配置的dataSource和parames列表中
    
    Args:
        f_meter_code: 设备代码(F_MeterCode)
        f_meter_param_code: 参数代码(F_MeterParamCode)
    
    Returns:
        tuple: (是否有效, 唯一标识符)
    """
    try:
        # 从配置中获取dataSource和parames
        data_sources = config['tables']['dataSource']
        parameters = config['tables']['parames']
        
        # 验证F_MeterCode是否在dataSource中
        if f_meter_code not in data_sources:
            logger.warning(f"F_MeterCode '{f_meter_code}' 不在配置的dataSource列表中")
            return False, None
        
        # 验证F_MeterParamCode是否在parames中
        if f_meter_param_code not in parameters:
            logger.warning(f"F_MeterParamCode '{f_meter_param_code}' 不在配置的parames列表中")
            return False, None
        
        # 创建唯一标识符
        unique_key = f"{f_meter_code}_{f_meter_param_code}"
        
        # 记录到映射表中
        if unique_key not in data_source_param_map:
            data_source_param_map[unique_key] = {
                'data_source': f_meter_code,
                'param': f_meter_param_code
            }
        
        return True, unique_key
        
    except KeyError as e:
        logger.error(f"配置文件中缺少必要配置: {str(e)}")
        return False, None
    except Exception as e:
        logger.error(f"验证数据源和参数时发生错误: {str(e)}")
        return False, None

def create_db_connection(max_retries=3):
    """创建数据库连接，支持重试
    
    Args:
        max_retries: 最大重试次数
    
    Returns:
        数据库连接对象或None
    """
    retry_count = 0
    while retry_count < max_retries:
        try:
            db_config = config['database']
            # SQL Server连接字符串
            conn_str = f"""
                DRIVER={{ODBC Driver 17 for SQL Server}};
                SERVER={db_config['host']},{db_config['port']};
                DATABASE={db_config['dbName']};
                UID={db_config['user']};
                PWD={db_config['password']};
            """
            connection = pyodbc.connect(conn_str)
            logger.info("数据库连接成功")
            return connection
        except pyodbc.Error as e:
            retry_count += 1
            logger.error(f"数据库连接失败 (第{retry_count}/{max_retries}次尝试): {str(e)}")
            if retry_count < max_retries:
                logger.info("3秒后重试...")
                time.sleep(3)
        except KeyError as e:
            logger.error(f"配置文件中缺少数据库配置: {str(e)}")
            return None
        except Exception as e:
            logger.error(f"数据库连接发生未知错误: {str(e)}")
            return None
    
    logger.error(f"数据库连接失败，已达到最大重试次数 ({max_retries})")
    return None

def get_latest_data():
    """根据dataSource和parames从数据库获取对应的数据，查询最新两条记录用于变化检测
    
    Returns:
        dict: 包含所有dataSource和parames组合的最新数据及上一条数据，格式为：
        {"dataSource_param": {"latest": {...}, "previous": {...}}}
    """
    connection = None
    try:
        connection = create_db_connection()
        if not connection:
            logger.error("无法建立数据库连接，无法获取数据")
            return None
        
        try:
            table_config = config['tables']
            table_name = table_config['tableName']
            fields = table_config['fields']
            data_sources = table_config['dataSource']
            parameters = table_config['parames']
        except KeyError as e:
            logger.error(f"配置文件中缺少表配置: {str(e)}")
            return None
        
        logger.info(f"开始查询数据，dataSource数量: {len(data_sources)}, parames数量: {len(parameters)}")
        
        result_data = {}
        
        try:
            with connection.cursor() as cursor:
                # 构建一个SQL查询，一次性获取所有dataSource和parameter组合的最新两条记录
                # 使用UNION ALL合并多个条件的查询结果
                union_queries = []
                query_params = []
                
                # 在SQL Server中，每个子查询需要有唯一的别名，并且ORDER BY需要配合TOP使用
                for i, data_source in enumerate(data_sources):
                    for j, param in enumerate(parameters):
                        # 为每个子查询创建唯一别名
                        subquery_alias = f"t{i}_{j}"
                        subquery = f"""
                        (SELECT * FROM (
                            SELECT TOP 2 {', '.join(fields)}
                            FROM {table_name} 
                            WHERE F_MeterCode = ? AND F_MeterParamCode = ? 
                            ORDER BY F_ReceiveTime DESC
                        ) AS {subquery_alias}
                        CROSS JOIN (VALUES (?, ?)) AS params(F_MeterCode, F_MeterParamCode)
                        )
                        """
                        union_queries.append(subquery)
                        query_params.extend([data_source, param, data_source, param])
                
                # 合并所有子查询
                query = ' UNION ALL '.join(union_queries)
                
                cursor.execute(query, query_params)
                results = cursor.fetchall()
                
                # 将结果转换为字典列表
                dict_results = []
                for row in results:
                    dict_row = {}
                    for i, col in enumerate(row.cursor_description):
                        dict_row[col[0]] = row[i]
                    dict_results.append(dict_row)
                
                # 将结果按dataSource和param分组
                grouped_results = {}
                for row in dict_results:
                    data_source = row['F_MeterCode']
                    param = row['F_MeterParamCode']
                    key = f"{data_source}_{param}"
                    
                    if key not in grouped_results:
                        grouped_results[key] = []
                    grouped_results[key].append(row)
                
                # 处理分组后的结果
                for key, rows in grouped_results.items():
                    # 初始化结果结构
                    result_data[key] = {'latest': None, 'previous': None}
                    
                    # 最新记录
                    result_data[key]['latest'] = {k: v for k, v in rows[0].items() if k not in ['F_MeterCode', 'F_MeterParamCode']}
                    result_data[key]['latest']['timestamp'] = time.time()
                    
                    # 如果有上一条记录
                    if len(rows) > 1:
                        result_data[key]['previous'] = {k: v for k, v in rows[1].items() if k not in ['F_MeterCode', 'F_MeterParamCode']}
                        result_data[key]['previous']['timestamp'] = time.time()
                    
                    # 记录日志时隐藏敏感信息
                    safe_latest = {k: v for k, v in result_data[key]['latest'].items() if not k.lower().__contains__('password')}
                    logger.info(f"成功获取数据 - {key}: 最新记录={safe_latest}, 上一条记录{'存在' if len(rows) > 1 else '不存在'}")
                
                # 检查是否有未查询到数据的组合
                for data_source in data_sources:
                    for param in parameters:
                        key = f"{data_source}_{param}"
                        if key not in result_data:
                            logger.warning(f"未查询到数据 - F_MeterCode={data_source}, F_MeterParamCode={param}")
            
            if result_data:
                logger.info(f"总共获取到 {len(result_data)} 个数据组合")
                return result_data
            else:
                logger.warning("未查询到任何数据记录")
                return None
                
        except pyodbc.Error as e:
            logger.error(f"数据库查询错误: {str(e)}")
            return None
            
    except Exception as e:
        logger.error(f"获取数据失败: {str(e)}")
        import traceback
        logger.error(f"异常堆栈: {traceback.format_exc()}")
        return None
    finally:
        if connection:
            connection.close()
            logger.info("数据库连接已关闭")

def compare_data(all_data):
    """比较最新数据与上一条数据是否相同，基于数据库中的两条记录进行变化检测
    
    Args:
        all_data: 包含最新数据和上一条数据的字典，格式为 {"dataSource_param": {"latest": {...}, "previous": {...}}}
    
    Returns:
        dict: 包含每个数据源和参数组合变化状态的字典，格式为 {"dataSource_param": True/False}
    """
    # 记录变化状态的结果字典
    change_status = {}
    
    # 如果数据为空，返回空结果
    if not all_data:
        logger.warning("没有数据可供比较")
        return change_status
    
    # 为每个数据源和参数组合进行比较
    for key, data_pair in all_data.items():
        # 确保有最新记录
        if not data_pair.get('latest'):
            logger.warning(f"缺少最新记录 - {key}")
            change_status[key] = False
            continue
        
        latest_record = data_pair['latest']
        previous_record = data_pair.get('previous')
        
        # 比较F_OrigValue是否相同
        new_value = latest_record.get('F_OrigValue', '')
        
        # 判断是否发生变化
        if not previous_record:
            # 只有最新记录，没有上一条记录，视为变化
            is_changed = True
            logger.debug(f"只有最新记录，无历史记录可比较 - {key}: 最新值='{new_value}'")
        else:
            old_value = previous_record.get('F_OrigValue', '')
            is_changed = str(old_value) != str(new_value)
            
            if is_changed:
                logger.info(f"数据发生变化 - {key}: 从 '{old_value}' 变为 '{new_value}'")
            else:
                logger.debug(f"数据无变化 - {key}: 值为 '{old_value}'")
        
        change_status[key] = is_changed
    
    # 记录总体变化情况
    changed_count = sum(change_status.values())
    total_count = len(change_status)
    
    if changed_count > 0:
        logger.info(f"总共有 {changed_count}/{total_count} 个数据组合发生变化")
    else:
        logger.info("所有数据组合均无变化")
    
    # 提取最新记录用于返回，格式与之前兼容
    latest_only_data = {}
    for key, data_pair in all_data.items():
        if data_pair.get('latest'):
            latest_only_data[key] = data_pair['latest']
    
    return change_status, latest_only_data

def create_modbus_client(max_retries=3):
    """创建modbus客户端连接，支持重试和持久化连接
    
    Args:
        max_retries: 最大重试次数
    
    Returns:
        Modbus客户端对象或None
    """
    global modbus_client
    
    # 如果已经有客户端并且连接有效，直接返回
    if modbus_client is not None:
        try:
            # 尝试发送一个简单的请求来检查连接是否仍然有效
            modbus_config = config['modbus']
            server_id = int(modbus_config['serverId'])
            modbus_client.read_holding_registers(0, 1, slave=server_id)
            logger.debug("Modbus连接仍然有效，重用现有客户端")
            return modbus_client
        except Exception as e:
            logger.warning(f"Modbus连接无效，将重新创建: {str(e)}")
            modbus_client = None
    
    retry_count = 0
    while retry_count < max_retries:
        try:
            try:
                modbus_config = config['modbus']
            except KeyError as e:
                logger.error(f"配置文件中缺少Modbus配置: {str(e)}")
                return None
            
            # 创建Modbus RTU客户端
            client = ModbusSerialClient(
                port=modbus_config['devid'],
                baudrate=int(modbus_config['port']),
                parity='N',
                stopbits=1,
                bytesize=8,
                timeout=2  # 增加超时时间
            )
            
            # 连接到设备
            if client.connect():
                logger.info(f"成功连接到Modbus设备: {modbus_config['devid']}")
                modbus_client = client
                return client
            else:
                retry_count += 1
                logger.error(f"无法连接到Modbus设备 (第{retry_count}/{max_retries}次尝试): {modbus_config['devid']}")
                if retry_count < max_retries:
                    logger.info("3秒后重试...")
                    time.sleep(3)
                    
        except ValueError as e:
            logger.error(f"Modbus配置参数错误: {str(e)}")
            return None
        except Exception as e:
            logger.error(f"创建Modbus客户端失败: {str(e)}")
            return None
    
    logger.error(f"创建Modbus客户端失败，已达到最大重试次数 ({max_retries})")
    return None

def push_data_to_modbus(all_data, change_status):
    """将数据推送至Modbus设备
    
    Args:
        all_data: 包含最新数据的字典，格式为 {"dataSource_param": {...}}
        change_status: 包含每个数据源和参数组合变化状态的字典，格式为 {"dataSource_param": True/False}
    
    Returns:
        dict: 包含每个数据源和参数组合推送结果的字典，格式为 {"dataSource_param": True/False}
    """
    if not all_data:
        logger.warning("没有数据可供推送")
        return {}
    
    if not change_status:
        logger.warning("没有变化状态信息")
        return {}
    
    # 初始化推送结果字典
    push_results = {}
    
    # 创建Modbus客户端
    client = create_modbus_client()
    if not client:
        logger.error("无法创建Modbus客户端，所有推送失败")
        # 设置所有结果为失败
        for key in all_data.keys():
            push_results[key] = False
        return push_results
    
    try:
        modbus_config = config['modbus']
        server_id = int(modbus_config['serverId'])
        # 获取modbus_addr配置
        modbus_addr_config = config.get('modbus_addr', {})
    except (KeyError, ValueError) as e:
        logger.error(f"Modbus配置错误: {str(e)}")
        # 设置所有结果为失败
        for key in all_data.keys():
            push_results[key] = False
        return push_results
    
    logger.info(f"使用配置的modbus_addr: {modbus_addr_config}")
    
    try:
        # 推送每个数据组合
        for key, data in all_data.items():
            try:
                # 从配置中获取寄存器地址
                if key not in modbus_addr_config:
                    logger.error(f"配置中找不到 {key} 的寄存器地址")
                    push_results[key] = False
                    continue
                
                # 获取地址并转换为整数
                try:
                    address = int(modbus_addr_config[key])
                    # 注意：这里的地址是从1开始的，需要减1转换为从0开始的索引
                    address = address - 1
                except ValueError as e:
                    logger.error(f"寄存器地址格式错误 - {key}: 值={modbus_addr_config[key]}, 错误={str(e)}")
                    push_results[key] = False
                    continue
                
                is_changed = change_status.get(key, False)
                
                # 提取F_OrigValue字段
                if 'F_OrigValue' not in data:
                    logger.error(f"数据中缺少F_OrigValue字段: {key}")
                    push_results[key] = False
                    continue
                
                # 决定要推送的值
                try:
                    # 获取F_OrigValue值
                    original_value = float(data['F_OrigValue'])
                    # 严格按照要求：数据变更时推送最新的F_OrigValue值，未变更时推送值为0
                    value_to_push = original_value if is_changed else 0.0
                    logger.info(f"准备推送数据 - {key}: F_OrigValue={original_value}, 是否变化={is_changed}, 推送值={value_to_push}, 寄存器地址={address}")
                except (ValueError, TypeError) as e:
                    logger.error(f"数据类型转换失败 - {key}: F_OrigValue={data['F_OrigValue']}, 错误={str(e)}")
                    push_results[key] = False
                    continue
                
                # 将float值转换为两个16位寄存器值（ABCD格式）
                try:
                    import struct
                    packed = struct.pack('!f', value_to_push)
                    registers = [int.from_bytes(packed[i:i+2], byteorder='big') for i in range(0, 4, 2)]
                except Exception as e:
                    logger.error(f"数据打包失败 - {key}: {str(e)}")
                    push_results[key] = False
                    continue
                
                # 写入保持寄存器
                try:
                    result = client.write_registers(address=address, values=registers, device_id=server_id)
                    
                    if result.isError():
                        logger.error(f"Modbus写入失败 - {key}: {result}")
                        push_results[key] = False
                    else:
                        logger.info(f"成功向Modbus设备推送数据 - {key}: 寄存器地址={address}, 值={registers}")
                        push_results[key] = True
                except ModbusException as e:
                    logger.error(f"Modbus异常 - {key}: {str(e)}")
                    push_results[key] = False
                    
            except Exception as e:
                logger.error(f"推送数据时发生错误 - {key}: {str(e)}")
                push_results[key] = False
        
        # 统计推送结果
        success_count = sum(push_results.values())
        total_count = len(push_results)
        logger.info(f"Modbus数据推送完成: 成功={success_count}, 失败={total_count - success_count}, 总计={total_count}")
        
        return push_results
            
    except Exception as e:
        logger.error(f"推送数据时发生严重错误: {str(e)}")
        import traceback
        logger.error(f"异常堆栈: {traceback.format_exc()}")
        return {}

def main_process():
    """主处理流程"""
    logger.info("========================================")
    logger.info("开始主处理流程")
    start_time = time.time()
    
    # 统计信息
    total_combinations = 0
    changed_combinations = 0
    successful_pushes = 0
    
    try:
        # 1. 获取数据
        logger.info("开始获取数据")
        all_data = get_latest_data()
        if not all_data:
            logger.error("未获取到任何数据，跳过后续处理")
            return False
        
        total_combinations = len(all_data)
        logger.info(f"成功获取 {total_combinations} 个数据组合")
        
        # 2. 验证数据组合的有效性
        logger.info("开始验证数据组合的有效性")
        valid_data = {}
        invalid_combinations = 0
        
        for key, data_pair in all_data.items():
            try:
                # 解析key，获取F_MeterCode和F_MeterParamCode
                parts = key.split('_', 1)
                if len(parts) != 2:
                    logger.error(f"无效的键格式: {key}")
                    invalid_combinations += 1
                    continue
                
                f_meter_code, f_meter_param_code = parts
                
                # 验证数据源和参数
                valid, _ = validate_data_source_param(f_meter_code, f_meter_param_code)
                if valid and data_pair.get('latest'):
                    valid_data[key] = data_pair
                    logger.debug(f"数据组合有效: {key}")
                else:
                    logger.debug(f"数据组合无效或缺少最新记录: {key}")
                    invalid_combinations += 1
                    
            except Exception as e:
                logger.error(f"验证数据组合 {key} 时出错: {str(e)}")
                invalid_combinations += 1
        
        logger.info(f"数据验证完成: 有效={len(valid_data)}, 无效={invalid_combinations}")
        
        if not valid_data:
            logger.error("没有有效的数据组合，跳过后续处理")
            return
        
        # 3. 比较数据变化
        logger.info("开始比较数据变化")
        # 适配compare_data函数返回两个值的情况
        change_status, latest_only_data = compare_data(valid_data)
        
        # 统计变化的组合数量
        changed_combinations = sum(change_status.values())
        logger.info(f"数据比较完成: 变化的组合数={changed_combinations}, 总有效组合数={len(valid_data)}")
        
        # 4. 推送数据到Modbus
        logger.info("开始推送数据到Modbus")
        # 使用latest_only_data进行推送
        push_results = push_data_to_modbus(latest_only_data, change_status)
        
        # 统计推送成功的数量
        if push_results:
            successful_pushes = sum(push_results.values())
        
        # 5. 计算耗时
        end_time = time.time()
        process_time = end_time - start_time
        
        # 6. 详细的结果日志
        logger.info(f"数据处理流程完成")
        logger.info(f"  - 总组合数: {total_combinations}")
        logger.info(f"  - 有效组合数: {len(valid_data)}")
        logger.info(f"  - 变化组合数: {changed_combinations}")
        logger.info(f"  - 推送成功数: {successful_pushes}")
        logger.info(f"  - 处理耗时: {process_time:.4f}秒")
        
        # 7. 如果有推送成功，认为整体成功
        is_success = successful_pushes > 0
        if is_success:
            logger.info("主处理流程执行成功")
        else:
            logger.warning("主处理流程执行，但没有成功推送任何数据")
            
        return is_success
              
    except Exception as e:
        logger.error(f"主处理流程发生严重错误: {str(e)}")
        import traceback
        logger.error(f"异常堆栈: {traceback.format_exc()}")
        
        # 记录处理失败的统计信息
        end_time = time.time()
        process_time = end_time - start_time
        logger.info(f"处理失败统计:")
        logger.info(f"  - 总组合数: {total_combinations}")
        logger.info(f"  - 变化组合数: {changed_combinations}")
        logger.info(f"  - 推送成功数: {successful_pushes}")
        logger.info(f"  - 处理耗时: {process_time:.4f}秒")
        
        logger.error("主处理流程执行失败")
        return False
    finally:
        # 记录处理耗时
        process_time = time.time() - start_time
        logger.info(f"主处理流程执行完毕，耗时: {process_time:.2f}秒")
        logger.info("========================================")
        logger.debug("主处理流程结束，确保所有资源已释放")
    
def start_scheduler():
    """启动定时调度器"""
    try:
        # 设置每分钟执行一次主处理流程
        schedule.every(1).minutes.do(main_process)
        logger.info("定时调度器已启动，每分钟执行一次数据处理")
        logger.info(f"数据库配置: {config['database']['host']}:{config['database']['port']}/{config['database']['dbName']}")
        logger.info(f"Modbus配置: {config['modbus']['mode']} {config['modbus']['devid']} {config['modbus']['port']}")
        
        # 立即执行一次主流程
        logger.info("立即执行一次数据处理...")
        main_process()
        
        # 持续运行调度器
        logger.info("开始进入定时调度循环，按Ctrl+C停止")
        while True:
            try:
                schedule.run_pending()
                time.sleep(1)
            except KeyboardInterrupt:
                logger.info("用户中断程序，正在退出...")
                break
    except Exception as e:
        logger.error(f"定时调度器发生错误: {str(e)}")
        import traceback
        logger.error(f"异常堆栈: {traceback.format_exc()}")
    finally:
        logger.info("程序已退出")

if __name__ == "__main__":
    try:
        config = load_config('config_server.json')
    except Exception as e:
        logger.critical(f"无法加载配置文件，程序退出: {str(e)}")
        exit(1)
    
    start_scheduler()